#define _CRT_SECURE_NO_WARNINGS 1
//time

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

#define Max 10
// 时间节点信息：用于记录进入停车场的时间和离开时间
typedef struct time
{
   int hour;
   int min;
} Time;

// 车辆信息节点：用来记录车辆车牌号，到达时间，离开时间。
typedef struct vehicle_node
{
   char num[10];
   Time reach;
   Time leave;
} CarNode;

// 停车场模拟站：用于存放停车场信息车辆出库时，临时使用数据结构与此时相同。
// 注意：车辆出库时，临时车站也用这一数据结构
typedef struct parking_stack
{
   CarNode* stack[Max + 1];
   int top;
} SeqStackCar;

// 等待区车辆节点 ：用于存储等待区车辆个体信息和位置信息。
typedef struct waiting_queue_node
{
   CarNode* data;
   struct waiting_queue_node* next;
} QueueNode;

// 等待区模拟队列：用来存储等待区的车辆队列信息
typedef struct waiting_queue
{
   QueueNode* head;
   QueueNode* rear;
} LinkQueueCar;

// 初始化栈
void initStack(SeqStackCar* s, int n)
{
   int i;
   s->top = 0;
   for (i = 0; i <= n; i++)
       s->stack[s->top] = NULL;
}

// 初始化等待区队列
int initQueue(LinkQueueCar* Q)
{
   Q->head = (QueueNode*)malloc(sizeof(QueueNode));
   if (Q->head != NULL)
   {
       Q->head->next = NULL;
       Q->rear = Q->head;
       return 1;
   }
   else
       return -1;
}

// 设定停车场容量
int getParkingCapacity()
{
   int n;
   printf("\n   欢迎光临万达停车场，");
   printf("本停车场管理实行24小时制，停车每分钟1000元.\n");
   printf("===============================================================\n");
   printf("\n请输入停车场可容纳的车(最多10辆):");
   scanf("%d", &n);
   fflush(stdin);
   while (n < 1 || n > 10)
   {
       printf("输入的车辆数不在要求范围内，请重新输入!");
       scanf("%d", &n);
       fflush(stdin);
   }
   return n;
}

// 打印车辆信息函数，打印收据
void printReceipt(CarNode* p)
{
   int A1, A2, B1, B2;
   int a, b, c;
   printf("\n请输入离开的时间:/**:**/");
   scanf("%d:%d", &(p->leave.hour), &(p->leave.min));
   fflush(stdin);
   while (p->leave.hour < p->reach.hour || (p->leave.hour == p->reach.hour && p->leave.min < p->reach.min) || p->leave.hour < 0 || p->leave.hour >= 24 || p->leave.min < 0 || p->leave.min >= 60)
   {
       printf("输入离开时间比进站时间早或格式错误，请重新输入!\n");
       scanf("%d:%d", &(p->leave.hour), &(p->leave.min));
       fflush(stdin);
   }
   printf("车场现在有一辆车离开，请便道里的第一辆车进入车场!\n");
   printf("出站的车的车牌号为:");
   puts(p->num);
   printf("\n");
   A1 = p->reach.hour;
   A2 = p->reach.min;
   B1 = p->leave.hour;
   B2 = p->leave.min;
   a = (B1 - A1) * 60 + B2 - A2;
   if (a >= 60)
   {
       b = a / 60;
       c = a - 60 * b;
   }
   else
   {
       b = 0;
       c = a;
   }
   // 打印收费收据
   printf("Welcome.\n            收        据\n");
   printf("===================================== 车牌号:");
   puts(p->num);
   printf("\n");
   printf("= ================================================\n");
   printf("|进车场时刻 | 出车场时刻 | 停留时间 | 应付（元）|\n|");
   printf("=================================================\n");
   printf("|   %d:%d", p->reach.hour, p->reach.min);
   printf("	|  %d:%d", p->leave.hour, p->leave.min);
   printf("	|  %d%d", b, c);
   printf(" | % 2.1f", 0.1 * a);
   printf("    |\n");
   printf("-----------------------------------------------\n");
   free(p);
}

// 车辆到达函数
int vehicleArrives(SeqStackCar *Enter, LinkQueueCar *W, int n)
{
   CarNode *p;
   QueueNode *t;
   int a, b;
   p = (CarNode *)malloc(sizeof(CarNode));
   fflush(stdin);
   printf("\n请输入车牌号(七位，例:陕A12345):\n");
   printf("请严格按照要求输入车牌号，否则系统会出错!\n");
   while (1)
   {
       a = strlen("陕A12345");
       scanf("%d", &n);
       b = strlen(gets(p->num));
       fflush(stdin);
       if (a != b)
       {
           printf("输入车牌号格式错误，请重新输入(七位)!\n");
           gets(p->num);
           fflush(stdin);
       }
       else  break;
       if (a != b)
           printf("输入车牌号格式错误，请重新输入(七位)!\n");
   }whi1(a != b);
   if (Enter->top < n)
   {
       Enter->top++;
       printf("\n车辆在车场第%d位置.", Enter->top);
       fflush(stdin);
       printf("\n请输入到达时间:/**;**/");
       scanf("%d:%d", &(p->reach.hour), &(p->reach.min));
       fflush(stdin);
       while (p->reach.hour < 0 || p->reach.hour >= 24 || p->reach.min < 0 || p->reach.min >= 60)
       {
           printf("输入的时间格式有错，请重新输入!");
           scanf("%d:%d", &(p->reach.hour), &(p->reach.min));
           fflush(stdin);
       }
       Enter->stack[Enter->top] = p;
       return 1;
   }
   else
   {
       printf("\n请该车在便道稍作等待！\n");
       t = (QueueNode*)malloc(sizeof(QueueNode));
       t->data = p;
       t->next = NULL;
       W->rear->next = t;
       W->rear = t;
       return 1;
   }
}

// 车辆离开函数
void vehicleLeaves(SeqStackCar* Enter, SeqStackCar* Temp, LinkQueueCar* W, int n)
{
   CarNode* p, * t;
   QueueNode* q;
   if (Enter->top > 0)
   {
       while (1)
       {
           printf("\n请输入要离开的车在车场的位置/1--%d/:", Enter->top);
           scanf("%d", &n);
           fflush(stdin);
           if (n >= 1 && n <= Enter->top)
               break;
       }
       while (Enter->top > n)
       {
           Temp->top++;
           Temp->stack[Temp->top] = Enter->stack[Enter->top];
           Enter->stack[Enter->top] = NULL;
           Enter->top--;
       }
       p = Enter->stack[Enter->top];
       Enter->stack[Enter->top] = NULL;
       Enter->top--;
       while (Temp->top >= 1)
       {
           Enter->top++;
           Enter->stack[Enter->top] = Temp->stack[Temp->top];
           Temp->stack[Temp->top] = NULL;
           Temp->top--;
       }
       printReceipt(p);
       if ((W->head != W->rear) && Enter->top < n)
       {
           q = W->head->next;
           t = q->data;
           Enter->top++;
           printf("\n现在请便道上的车进入车场,该车的车牌号为:");
           puts(t->num);
           printf("\n该车进入车场第%d位置.", Enter->top);
           printf("\n请输入现在的时间(即该车进站的时间)/**:**/: ");
           scanf("%d:%d", &(t->reach.hour), &(t->reach.min));
           fflush(stdin);
           while (t->reach.hour < 0 || t->reach.hour >= 24 || t->reach.min < 0 || t->reach.min >= 60)
           {
               printf("输入的时间格式有错，请重新输入!");
               scanf("%d:%d", &(t->reach.hour), &(t->reach.min));
               fflush(stdin);
           }
           W->head->next = q->next;
           if (q == W->rear)
               W->rear = W->head;
           Enter->stack[Enter->top] = t;
           free(q);
       }
       else
           printf("\n 目前便道里没车\n");
   }
   else
       printf("\n目前无车，来车请进车场！\n");
}

// 输出停车场停车信息函数
void listParkingInfo(SeqStackCar* S)
{
   int i;
   if (S->top > 0)
   {
       printf("\n                             车场存车信息\n");
       printf("\n                   位置         到达时间      车牌号\n");
       for (i = 1; i <= S->top; i++)
       {
           printf("\n                               %d ", i);
           printf("      %d :%d     ", S->stack[i]->reach.hour, S->stack[i]->reach.min);
           puts(S->stack[i]->num);
       }
   }
   else
       printf("\n目前车场里没有车");
}

// 输出等待区信息函数
void listWaitingQueueInfo(LinkQueueCar* W)
{
   QueueNode* p;
   p = W->head->next;
   if (W->head != W->rear)
   {
       printf("\n日前正在等待车辆的号码为:");
       while (p != NULL)
       {
           puts(p->data->num);
           printf("");
           p = p->next;
       }
   }
   else
       printf("\n日前便道里没有车.");
}

// 车辆信息主控函数
void listVehicleInfo(SeqStackCar S, LinkQueueCar W)
{
   int flag, tag;
   flag = 1;
   while (flag)
   {
       printf("\n1.车场\n2.便道\n3.返回\n");
       while (1)
       {
           printf("\n请选择 1|2|3:");
           scanf("%d", &tag);
           fflush(stdin);
           while (tag < 1 || tag > 3)
           {
               printf("输入有误，请按要求重新输入!");
               scanf("%d", &tag);
               fflush(stdin);
           }
           break;
       }
       switch (tag)
       {
       case 1:
           listParkingInfo(&S);
           break;
       case 2:
           listWaitingQueueInfo(&W);
           break;
       case 3:
           flag = 0;
           break;
       default:
           break;
       }
   }
}

int main()
{
   SeqStackCar Enter, Temp;
   LinkQueueCar Wait;
   int choice;
   int capacity;
   capacity = getParkingCapacity();
   initStack(&Enter, capacity);
   initStack(&Temp, capacity);
   initQueue(&Wait);
   while (1)
   {
       printf("      *****************************************\n");
       printf("      1.车辆进站");
       printf("2.车辆出站");
       printf("3.存车信息");
       printf("4.退出系统\n");
       printf("      *****************************************\n");
       while (1)
       {
           printf("请选择: 1|2|3|4.\n");
           scanf("%d", &choice);
           fflush(stdin);
           while (choice > 4 || choice < 1)
           {
               printf("输入有误，请重新输入!");
               scanf("%d", &choice);
               fflush(stdin);
           }
           break;
       }
       switch (choice)
       {
       case 1:
           vehicleArrives(&Enter, &Wait, capacity);
           break;
       case 2:
           vehicleLeaves(&Enter, &Temp, &Wait, capacity);
           break;
       case 3:
           listVehicleInfo(Enter, Wait);
           break;
       case 4:
           exit(0);
       default:
           break;
       }
   }
   return 0;
}
